import { useObserver } from "mobx-react-lite";
import _ from 'lodash';
import styles from './index.module.less';
import { AdvancedTable } from "../advanced-table";
import { makeAutoObservable, runInAction, toJS } from "mobx";
import React from "react";
import { Divider, Flex, type TableColumnType, type TablePaginationConfig, Button } from "@/components/base";
import { RedoOutlined } from "@ant-design/icons";
import { PageFilter, type IPageFilterProps } from "@/components/page-filter";
import * as UI from "./ui";
import type { SizeType } from "antd/lib/config-provider/SizeContext";
import { useRowSelection } from "@/utils/hooks/use-row-selection";
import type { ICapability } from "@/components/capability";
import { useLoading } from "@shared/utils/hooks";
import { useLocation, useNavigate } from "react-router-dom";


/** 操作列，参数 */
export interface IOperation {
    /**
     * 操作列宽度
     * @default 100
     */
    width?: number;

    /**
     * 操作能力
     * @default '操作'
     */
    expandOutList: ICapability[];

    /**
     * 操作数据
     * 用于传递给操作能力的额外数据
     */
    data?: any;
}

/**
 * API 接口类型
 */
type IApi = (params: { page: number, pageSize: number, searchData?: any, sorter?: any }) => Promise<{ items: any[], pagination: { total: number } } | undefined>

const PageTableUi = function <IDataSource = any, ISearchData = any>(props: {
    /** 
     * 表格配置
     * @example
     * ```tsx
     * columns={[
     *   { title: '名称', dataIndex: 'name', key: 'name', width: 200 },
     *   { title: '状态', dataIndex: 'status', key: 'status', width: 100, render: (text) => text === 'enabled' ? '启用' : '禁用' },
     *   { title: '日期', dataIndex: 'date', key: 'date', width: 150, render: (text) => new Date(text).toLocaleDateString() },
     * ]}
     * ```
     * */
    columns?: TableColumnType<IDataSource>[],

    /**
     * 筛选条件
     */
    filterProps?: IPageFilterProps<ISearchData>,

    /** 
     * 表格控制器
     */
    controller?: Controller<IDataSource>;

    /**
     * 是否启用行选择
     * @default false
     * */
    isRowSelection?: boolean;

    /**
     * 操作列
     * 用于展示每行数据的操作按钮
     */
    operation?: IOperation;

    /**
     * 行键
     * 用于唯一标识每一行数据
     */
    rowKey?: string;

    /**
     * API 接口
     * 用于获取表格数据
     * 如果提供了此接口，则会自动调用该接口获取数据
     **/
    api?: IApi;

    /** 扩展左边 */
    extendLeft?: React.ReactNode | React.ReactNode[];

    /** 扩展右边 */
    extendRight?: React.ReactNode | React.ReactNode[];

    /** 扩展上边 */
    extendTop?: React.ReactNode | React.ReactNode[];

    /** 扩展下边 */
    extendBottom?: React.ReactNode | React.ReactNode[];
}) {
    const { columns = [], filterProps, extendLeft, extendRight, extendTop, extendBottom, isRowSelection, operation } = props;
    const { controller, refresh, rowSelection, selectedRows, setSelectedRow, loading } = useController<IDataSource>(props.controller, props.api, props.rowKey);
    const { size, dataSource, pagination, sorter } = useObserver(() => controller);
    const { setRoutingStorage } = useRoutingStorage(controller); // 路由存储

    // 在 PageTableUi 组件中使用
    const processedColumns = React.useMemo(() => {
        return processColumnsWithSort(columns, sorter);
    }, [columns, sorter]);

    /** 操作列 */
    const operationColumn = React.useMemo<TableColumnType>(() => {
        if (!operation || !operation.expandOutList || operation.expandOutList.length === 0) return undefined;
        return {
            title: '操作',
            key: 'operation',
            width: operation.width || 100,
            fixed: 'right',
            render: (_text: any, record: IDataSource, index: number) => (
                <AdvancedTable.Operate
                    index={index}
                    data={{ record, refresh, selectedRows, ...operation.data }}
                    expandOutList={operation.expandOutList}
                />
            ),
        }
    }, [operation, refresh, selectedRows]);

    /**
     * 获取表格数据
     * */
    React.useEffect(() => {
        refresh();
        return () => {
            refresh.cancel(); // 清除防抖函数
        }
    }, [refresh])

    /**
     * 数据源变化，清空选中行
     * 这是为了确保在数据源变化时，选中的行不会保留之前
     */
    React.useEffect(() => { setSelectedRow([]) }, [dataSource, setSelectedRow])

    return (
        <Controller.context.Provider value={controller}>
            <div className={styles['page-table-ui']} >
                <div>
                    <PageFilter<ISearchData>
                        {...filterProps}
                        searchData={controller.searchData}
                        onSearch={e => {
                            const pagination = toJS(controller.pagination);
                            const sorter = toJS(controller.sorter);
                            setRoutingStorage({ ...pagination, current: 1 }, e, sorter);
                        }}
                    />
                </div>
                {
                    extendTop &&
                    <>
                        <Divider style={{ margin: 0 }} />
                        {extendTop}
                    </>
                }
                <Divider style={{ margin: 0 }} />
                <Flex justify='space-between' align='center' gap={5} className={styles['page-table-title']}>
                    {extendLeft}
                    <div style={{ flex: 1 }} />
                    {extendRight}
                    <Button onClick={refresh} size='small' icon={<RedoOutlined />} />
                    <UI.TableSize />
                    {/* <Button type='text' icon={<SettingOutlined />} /> */}
                </Flex>
                {
                    extendBottom &&
                    <>
                        <Divider style={{ margin: 0 }} />
                        {extendBottom}
                    </>
                }
                <AdvancedTable<IDataSource>
                    size={size}
                    bordered
                    loading={loading}
                    className={styles['page-table']}
                    rowKey={props.rowKey}
                    columns={[...processedColumns, operationColumn].filter(e => !!e)}
                    rowSelection={isRowSelection ? rowSelection : undefined}
                    dataSource={dataSource || []}
                    scroll={{ x: 'max-content' }}
                    onChange={(pagination, _, sorter) => {
                        const searchData = toJS(controller.searchData);
                        setRoutingStorage(pagination, searchData, sorter);
                    }}
                    pagination={{
                        pageSize: pagination?.pageSize || 10,
                        total: pagination?.total || 0,
                        current: Math.max(1, pagination?.current),
                        pageSizeOptions: ['1', '10', '20', '50', '100'],
                        showSizeChanger: true,
                        showQuickJumper: true,
                        showTotal: ((total, range) => `第 ${range[0]} - ${range[1]} 条，共有 ${total} 条` +
                            (isRowSelection ? `｜选中 ${selectedRows.length} 条` : '')),
                    }}
                />
            </div>
        </Controller.context.Provider>
    )

    // return useObserver(() => {
    //     const { size, dataSource, pagination } = controller;
    //     return (

    //     )
    // })
}

/** 
 * 表格控制器
 * 用于处理表格的状态和行为
 * 例如：分页、排序、筛选等
 */
function useController<IDataSource>(
    oldController?: Controller,
    api?: IApi,
    rowKey?: string,
) {
    const controller = React.useMemo(() => oldController || new Controller<IDataSource>(), [oldController]);
    const { searchData, sorter, pagination } = useObserver(() => ({ ...controller }));
    const { current, pageSize } = useObserver(() => ({ ...pagination }));
    const { rowSelection, selectedRows, setSelectedRow } = useRowSelection<IDataSource>(rowKey || 'id');
    const { run, loading } = useLoading();

    /** 刷新列表数据 */
    const refresh = React.useMemo(() => _.debounce(async () => {
        if (!controller.api) return;
        run(async () => {
            const data = await controller.api({ pageSize, page: current, searchData, sorter });
            runInAction(() => {
                controller.dataSource = data?.items || [];
                controller.pagination = {
                    ...controller.pagination,
                    total: data?.pagination?.total || 0,
                };
            })
        }, (error => {
            console.error('获取表格数据失败', error);
            runInAction(() => {
                controller.dataSource = [];
                controller.pagination = {
                    ...controller.pagination,
                    total: 0,
                };
            })
        }))
    }), [controller, run, pageSize, current, searchData, sorter]);

    // 如果提供了 API 接口，则将其绑定到控制器
    React.useEffect(() => {
        if (api) {
            controller.api = api;
        } else if (!controller.api) {
            console.warn('未提供 API 接口，无法获取表格数据');
        }
    }, [api, controller]);

    return {
        loading,
        controller,
        refresh,
        rowSelection,
        selectedRows,
        setSelectedRow,
    }
}

/**
 * 表格控制器类
 * 用于管理表格的数据源、分页等状态
 * @template IDataSource - 数据源类型
 */
class Controller<IDataSource = any> {

    /** 上下文 */
    static context = React.createContext<Controller<any>>(undefined as any);

    size?: SizeType = 'middle';

    /** 数据源 */
    dataSource?: IDataSource[] = [];

    /** 分页配置 */
    pagination?: TablePaginationConfig;

    /**
     * 排序配置
     * 用于存储表格的排序状态
     */
    sorter?: any

    /**
     * 搜索数据
     * 用于存储用户输入的筛选条件
     */
    searchData?: any

    /** api 方法 */
    api?: IApi;

    constructor() {
        makeAutoObservable(this);
    }
}

/** 翻页数据路由存储 */
function useRoutingStorage(controller: Controller) {
    const navigate = useNavigate();
    const location = useLocation();

    /** 
     * 设置分页数据、筛选数据、排序数据 
     * @param pagination - 分页配置
     * @param searchData - 筛选数据
     * @param sorter - 排序数据
     * */
    const setRoutingStorage = React.useCallback((pagination: TablePaginationConfig, searchData?: any, sorter?: any) => {

        const params: Record<string, any> = {
            page: pagination?.current || 1,
            pageSize: pagination?.pageSize || 10,
        };

        navigate({
            pathname: location.pathname,
            search: new URLSearchParams(params).toString(),
        }, {
            replace: true,
            state: { searchData, sorter: { field: sorter.field, order: sorter.order } }
        });
    }, [navigate, location.pathname]);

    // location 变化，把数据写进 controller
    React.useEffect(() => {
        const params = new URLSearchParams(location.search);
        const page = parseInt(params.get('page') || '1', 10);
        const pageSize = parseInt(params.get('pageSize') || '10', 10);
        const searchData = location.state?.searchData;
        const sorter = location.state?.sorter;
        runInAction(() => {
            controller.pagination = {
                current: page,
                pageSize: pageSize,
                total: controller.pagination?.total || 0,
            };
            controller.searchData = searchData;
            controller.sorter = sorter;
        });
    }, [location.search, location.state, controller]);

    return {
        /** 设置分页数据、筛选数据、排序数据 */
        setRoutingStorage,
    }
}

/**
 * PageTable 组件
 * 用于展示分页表格，支持筛选、排序等功能
 * @template IDataSource - 数据源类型
 * @template ISearchData - 筛选数据类型
 */
export const PageTable = Object.assign(PageTableUi, {
    /** 表格控制器 */
    useController,

    /** 表格控制器类 */
    Controller,

    /** 翻页数据路由存储 */
    useRoutingStorage,
});

/** 处理列排序显示的辅助函数 */
const processColumnsWithSort = (columns: TableColumnType[], sorter?: any) => {
    return columns.map(column => {
        if (column.sorter && column.key) {
            return {
                ...column,
                sortOrder: sorter?.field === column.key ? sorter.order : null,
            };
        }
        return column;
    }) as TableColumnType[];
};

/** 校验是否空对象,是返回源对象，不是返回空 */
// function isEmptyObject<T>(obj: T): T | undefined {
//     if (obj && typeof obj === 'object' && Object.keys(obj).length === 0) {
//         return undefined; // 返回 undefined 表示空对象
//     }
//     return obj; // 返回原对象
// }